import { ApiResponse } from "@/types/interface";
import { getSesstion, isWindow } from "./session";

// fetchClient.ts
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';
export const baseUrl = "https://lizhan.fun"
//@ts-ignore
interface FetchOptions extends RequestInit {
    retry?: number;
    retryDelay?: number;
    requestInterceptor?: (config: RequestInit) => RequestInit;
    responseInterceptor?: (response: Response) => Promise<Response>;
    timeout?: number; // 毫秒，超时自动中止
    signal?: AbortSignal; // 外部传入的信号
    credentials?: string
}

const defaultRetry = 2;
const defaultDelay = 500;

function delay(ms: number) {
    return new Promise((resolve) => setTimeout(resolve, ms));
}

async function fetchWithRetry(
    url: string,
    options: FetchOptions = {},
    retryCount: number = options.retry ?? defaultRetry
): Promise<Response> {
    // console.log("attempt", options);
    const token = getSesstion("token")
    //@ts-ignore
    let config: RequestInit = {
        ...options,
        headers: {
            // 'Content-Type': 'application/json',
            ...(token ? { Authorization: `Bearer ${token}` } : {}),

            ...(options.headers || {}),
        },
    };

    // if (token) {
    //     config.headers = {
    //         ...config.headers,

    //     };
    // }
    if (options.requestInterceptor) {
        config = options.requestInterceptor(config);
    }

    let lastError: any;

    for (let attempt = 0; attempt <= retryCount; attempt++) {
        // console.log("attempt", config);
        // AbortController 支持（每次重试都要新建）
        const controller = new AbortController();
        const timeout = options.timeout;
        const timer = timeout
            ? setTimeout(() => controller.abort(), timeout)
            : null;

        // 合并外部传入 signal
        if (options.signal) {
            console.log("abort")
            options.signal.addEventListener('abort', () => { console.log("abort"); controller.abort() });
        }

        config.signal = controller.signal;

        try {
            console.log(config)
            const response = await fetch(url, config);
            if (timer) clearTimeout(timer);

            if (options.responseInterceptor) {
                return await options.responseInterceptor(response);
            }

            if (!response.ok && attempt < retryCount) {
                throw new Error(`HTTP error: ${response.status}`);
            }

            return response;
        } catch (err) {
            lastError = err;
            //@ts-ignore
            if (err.name === 'AbortError') throw err;
            if (attempt < retryCount) await delay(options.retryDelay ?? defaultDelay);
        }
    }

    throw lastError;
}


async function request<T = any>(
    url: string,
    method: HttpMethod,
    data?: any,
    options?: FetchOptions
): Promise<ApiResponse<T>> {
    const init: FetchOptions = {
        method,
        ...options,
    };

    if (data && method !== 'GET') {
        if ((data instanceof (FormData)))
            init.body = data
        else {
            init.body = JSON.stringify(data);
            if (!init.headers)
                init.headers = {}
            //@ts-ignore
            if (!init.headers["Content-Type"]) {
                //@ts-ignore
                init.headers["Content-Type"] = 'application/json'

            }

        }
    }
    // if (!url.includes("http"))
    //     url = baseUrl + url;
    // console.log(url)

    const response = await fetchWithRetry(url, init);
    const contentType = response.headers.get('content-type');

    if (contentType?.includes('application/json')) {
        const res = await response.json() as any
        // console.log(response)
        // 检查当前是否在登录页面，避免登录失败时重定向
        const isLoginPage = isWindow && window.location.pathname === '/login';
        if (!isLoginPage && (response.status == 401 || res.code == 401 || (res.msg && res.msg.includes('token失效')))) {
            isWindow && (window.location.href = process.env.NODE_ENV == "development" ? "/login" : '/ai/login')

        }
        return res;
    } else if (contentType?.includes('stream')) {
        //@ts-ignore
        return response
    } else {
        return response.text() as any;
    }
}

const http = {
    get: <T>(url: string, options?: FetchOptions): Promise<ApiResponse<T>> => request<T>(url, 'GET', null, options),
    post: <T>(url: string, data: any, options?: FetchOptions): Promise<ApiResponse<T>> => request<T>(url, 'POST', data, options),
    put: <T>(url: string, data: any, options?: FetchOptions): Promise<ApiResponse<T>> => request<T>(url, 'PUT', data, options),
    delete: <T>(url: string, data?: any, options?: FetchOptions): Promise<ApiResponse<T>> => request<T>(url, 'DELETE', data, options),
};

export default http;


